package com.kingyun.gpsinspection.purificationservice.services.tdm.innerservice.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cqhilink.api.common.utils.UniqueUtil;
import com.kingyun.gpsinspection.purificationservice.common.activiti.ActivitiConstants;
import com.kingyun.gpsinspection.purificationservice.common.utils.ConstantUtil;
import com.kingyun.gpsinspection.purificationservice.common.utils.FileTypeUtil;
import com.kingyun.gpsinspection.purificationservice.dao.mapper.iam.accessory.OrganizationMapper;
import com.kingyun.gpsinspection.purificationservice.dao.mapper.tdm.*;
import com.kingyun.gpsinspection.purificationservice.facade.model.File;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.Employee;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.EmployeeVo;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.RedisValue;
import com.kingyun.gpsinspection.purificationservice.facade.model.som.User;
import com.kingyun.gpsinspection.purificationservice.facade.model.tdm.*;
import com.kingyun.gpsinspection.purificationservice.facade.service.activiti.base.WorkFlowService;
import com.kingyun.gpsinspection.purificationservice.facade.service.jsm.employee.JsmEmployeeService;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * Created by liyi on 2016/11/30.
 * 常规操作业务层
 */
public class NormalOperationServiceImpl implements NormalOperationService {
    public Logger logger = LoggerFactory.getLogger(this.getClass());

    public static final String NORMAL_FLOW_KEY = "normal";

    // BPM
    @Autowired
    public IBMBPMService ibmbpmService;
    @Autowired
    public NormalOperationMapper normalOperationMapper;
    @Autowired
    public WorkOrderService workOrderService;
    @Autowired
    public TaskLinkService taskLinkService;
    @Autowired
    public TaskLinkMapper taskLinkMapper;
    @Autowired
    private TdmFileMapper tdmFileMapper;
    @Autowired
    private TaskRelationService taskRelationService;
    @Autowired
    public TdmWorkOrderMapper tdmWorkOrderMapper;
    @Autowired
    public WorkOrderEmployeeMapper workOrderEmployeeMapper;
    @Autowired
    public MessageImpartService messageImpartService;
    @Autowired
    public MessageImpartMapper messageImpartMapper;
    @Autowired
    private WorkFlowService workFlowService;
    @Autowired
    private OrganizationMapper organizationMapper;
    @Autowired
    private JsmEmployeeService jsmEmployeeService;

    /**
     * 新增常规操作信息并发起流程
     *
     * @param employeeVo
     * @param normalOperation 常规操作信息
     * @param workOrderList   工单信息
     * @param uploadFiles     上传附件
     * @param deletedFiles    删除附件
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public NormalOperation saveNormalOperation(EmployeeVo employeeVo, NormalOperation normalOperation, List<WorkOrderVo> workOrderList, String uploadFiles, String deletedFiles) throws Exception {
        // 设置主键ID
        normalOperation.setNormalOperationId(UniqueUtil.uuid());
        // 设置创建人ID
        normalOperation.setCreateUserId(employeeVo.getEmployeeId());
        // 设置创建时间
        normalOperation.setCreateTime(new Date());
        // 设置修改人ID
        normalOperation.setModifyUserId(employeeVo.getEmployeeId());
        // 设置修改时间
        normalOperation.setModifyTime(new Date());
        // 状态1是正常；0是删除
        normalOperation.setIsDelete((short) 1);
        // 状态1是启用；0是关闭
        normalOperation.setIsEnable((short) 1);
        // 当前节点
        normalOperation.setNode((short) 0);
        // 设置审核状态
        normalOperation.setAuditStatus((short) 1);
        // 任务状态
        normalOperation.setTaskStatus((short) 1);
        // 保存常规操作信息
        normalOperationMapper.insertSelective(normalOperation);

        //保存附件
        saveAttach(normalOperation, uploadFiles, deletedFiles);

        // 保存工单
        workOrderService.saveWorkOrderList(employeeVo, normalOperation.getNormalOperationId(), normalOperation.getTaskType(), workOrderList);

        //进入现场操作：所有工单状态改为可用
        tdmWorkOrderMapper.updateStatusEnableByTaskId(normalOperation.getNormalOperationId());
        normalOperation.setTaskStatus((short) 2);
        normalOperationMapper.updateByPrimaryKeySelective(normalOperation);

        //开启流程
        Map map = achievePersons(workOrderList);
        //发起流程
        workFlowService.startProcessInstanceByKey(NORMAL_FLOW_KEY, normalOperation.getNormalOperationId(), map, employeeVo.getEmployeeId());
        return normalOperation;
    }


    /**
     * 根据工单来获取审批人员信息
     */
    private Map achievePersons(List<WorkOrderVo> workOrderList) {
        Map map = new HashMap<>();
        List<String> names = new ArrayList<>();
        for (WorkOrderVo workOrderVo : workOrderList) {
            if (null != workOrderVo.getOrgId() && workOrderVo.getOrgId() != "") {
                List<User> list = organizationMapper.queryUsersByOrgId(workOrderVo.getOrgId());
                for (User user : list) {
                    names.add(user.getUserId());
                }
            } else if (null != workOrderVo.getUserId() && workOrderVo.getUserId() != "") {
                Employee employee = jsmEmployeeService.queryByKeyId(workOrderVo.getUserId());
                names.add(employee.getEmployeeId());
            }
        }
        map.put(ActivitiConstants.MANUAL_PERSON, names);
        return map;
    }

    /**
     * 保存附件
     *
     * @param normalOperation
     * @param uploadFiles
     * @param deletedFiles
     */
    public int saveAttach(NormalOperation normalOperation, String uploadFiles, String deletedFiles) {
        int a = 0;

        //保存附件
        if (StringUtils.isNotBlank(uploadFiles)) {
            //强制转换成集合
            List<File> listFiles = JSON.parseArray(uploadFiles, File.class);
            //重新设置附件属性
            for (int i = 0; i < listFiles.size(); i++) {
                File _file = listFiles.get(i);
                //设置主键
                _file.setFileId(UniqueUtil.uuid());
                //设置业务数据id
                _file.setBusinessId(normalOperation.getNormalOperationId());
                _file.setFileType((short) FileTypeUtil.getFileTypeByFileName(_file.getFileName()));
            }
            //必须判断非空
            if (listFiles != null && listFiles.size() > 0) {
                a += tdmFileMapper.insertByList(listFiles);
            }
        }
        //需要删除的附件信息
        if (StringUtils.isNotBlank(deletedFiles)) {
            //强制转换成集合
            List<File> listFiles = JSON.parseArray(deletedFiles, File.class);
            if (listFiles != null && listFiles.size() > 0) {
                int len = listFiles.size();
                for (int i = 0; i < len; i++) {
                    File _file = listFiles.get(i);
                    a += tdmFileMapper.deleteByPrimaryKey(_file.getFileId());
                }
            }
        }

        return a;
    }

    /**
     * 保存分析处理关联常规操作任务
     *
     * @param employeeVo
     * @param normalOperation
     * @param taskRelation
     * @param workOrderList
     * @param uploadFiles
     * @param deletedFiles
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public NormalOperation save(EmployeeVo employeeVo, NormalOperation normalOperation, TaskRelation taskRelation, List<WorkOrderVo> workOrderList, String uploadFiles, String deletedFiles) throws Exception {
        // 如果参数为null则返回null
        if (normalOperation != null) {
            // 设置主键ID
            normalOperation.setNormalOperationId(UniqueUtil.uuid());
            // 设置创建人ID
            normalOperation.setCreateUserId(employeeVo.getEmployeeId());
            // 设置创建时间
            normalOperation.setCreateTime(new Date());
            // 设置修改人ID
            normalOperation.setModifyUserId(employeeVo.getEmployeeId());
            // 设置修改时间
            normalOperation.setModifyTime(new Date());
            // 状态1是正常；0是删除
            normalOperation.setIsDelete((short) 1);
            // 状态1是启用；0是关闭
            normalOperation.setIsEnable((short) 1);
            // 当前节点
            normalOperation.setNode((short) 0);
            // 设置审核状态
            normalOperation.setAuditStatus((short) 1);
            // 任务状态
            normalOperation.setTaskStatus((short) 1);
            // 设置常规操作的任务状态
            normalOperation.setTaskStatus((short) 1);
            // 保存常规操作信息
            normalOperationMapper.insertSelective(normalOperation);

            // 设置主键ID
            taskRelation.setTaskRelationId(UniqueUtil.uuid());
            taskRelation.setMasterTaskId(taskRelation.getMasterTaskId());
            taskRelation.setMasterTaskType((short) 5);
            taskRelation.setRelatedTaskId(normalOperation.getNormalOperationId());
            taskRelation.setRelatedTaskType(normalOperation.getTaskType());
            taskRelationService.save(taskRelation);

            // 保存附件
            saveAttach(normalOperation, uploadFiles, deletedFiles);

            // 保存工单：删除旧工单，新增新工单
            saveWorkOrderList(employeeVo, normalOperation, workOrderList);

            return normalOperation;
        } else {
            return null;
        }
    }

    /**
     * 根据任务信息保存工单
     *
     * @param employeeVo
     * @param normalOperation
     * @param workOrderList
     * @return
     */
    public int saveWorkOrderList(EmployeeVo employeeVo, NormalOperation normalOperation, List<WorkOrderVo> workOrderList) {
        int a = 0;

        if (workOrderList != null && workOrderList.size() > 0) {
            //注意思路：先删除后新增
            List<WorkOrder> oldWorkOrderList = tdmWorkOrderMapper.findListByTaskId(normalOperation.getNormalOperationId());

            //先根据工单Id删除工单和人员的关系表
            if (oldWorkOrderList != null && oldWorkOrderList.size() > 0) {
                for (WorkOrder oldWorkOrder : oldWorkOrderList) {
                    if (oldWorkOrder != null && oldWorkOrder.getWorkOrderId() != null) {
                        a += workOrderEmployeeMapper.deleteByWorkOrderId(oldWorkOrder.getWorkOrderId());
                    }
                }
            }

            //再根据任务Id删除该任务对应的工单：
            a += tdmWorkOrderMapper.deleteByTaskId(normalOperation.getNormalOperationId());

            //重要方法：给List中的元素回设置
            for (WorkOrderVo workOrder : workOrderList) {
                //重新设置主键ID
                workOrder.setWorkOrderId(UniqueUtil.uuid());
                workOrder.setTaskId(normalOperation.getNormalOperationId());
                //无法保存任务环节ID
                //workOrder.setTaskLinkId();
                workOrder.setTaskType(normalOperation.getTaskType());
                workOrder.setCreateUserId(employeeVo.getEmployeeId());
                workOrder.setModifyUserId(employeeVo.getEmployeeId());
                //工单状态：-1预处理，0创建，1作业条件检查，2作业前准备，3操作申请（关键操作--才会申请），4审核通过，5审核不通过，6已经完成，7已关闭
                workOrder.setStatus((short) -1);
                //1是删除；0是正常
                workOrder.setIsDelete((short) 0);
                //0未下载；已经下载
                workOrder.setIsDownload((short) 0);
                //0无法完成；1可以完成
                workOrder.setCanFinish((short) 1);
                //0未确认；1已经确认
                workOrder.setConfirmStatus((short) 0);

                //先保存工单
                a += tdmWorkOrderMapper.insertNew(workOrder);

                //保存工单和人员的关系表：
                if (workOrder.getUserId() != null) {
                    String[] array = workOrder.getUserId().split(",");

                    if (array != null && array.length > 0) {
                        for (int i = 0; i < array.length; i++) {
                            if (StringUtils.isNotBlank(array[i])) {
                                WorkOrderEmployee workOrderEmployee = new WorkOrderEmployee();
                                workOrderEmployee.setWorkOrderEmployeeId(UniqueUtil.uuid());
                                workOrderEmployee.setEmployeeId(array[i]);
                                workOrderEmployee.setWorkOrderId(workOrder.getWorkOrderId());

                                a += workOrderEmployeeMapper.insert(workOrderEmployee);
                            }
                        }
                    }
                }
            }
        }
        return a;
    }

    /**
     * 修改常规操作
     *
     * @param employeeVo
     * @param normalOperation
     * @param workOrderList
     * @param uploadFiles
     * @param deletedFiles    @return
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int update(EmployeeVo employeeVo, NormalOperation normalOperation, List<WorkOrderVo> workOrderList, String uploadFiles, String deletedFiles) {
        // 判空
        if (normalOperation == null) {
            return 0;
        }

        int a = 0;
        normalOperation.setModifyTime(new Date());
        normalOperation.setModifyUserId(employeeVo.getEmployeeId());
        //苏公车注释原因：不能用下面的修改，因为commandId，planId，workInstanceId只能有一个有值，另外两个必须为空
        a += normalOperationMapper.updateByPrimaryKeyNew(normalOperation);

        // 保存工单：删除旧工单，新增新工单 苏公车添加
        a += saveWorkOrderList(employeeVo, normalOperation, workOrderList);

        // 保存附件：苏公车添加
        a += saveAttach(normalOperation, uploadFiles, deletedFiles);

        return a;
    }

    /**
     * 查根据询piid常规操作
     *
     * @param piid
     * @return
     * @throws Exception
     */
    @Override
    public NormalOperationVo findNormalOperationByPiid(String piid) throws Exception {
        // 判空
        if (StringUtils.isBlank(piid)) {
            return null;
        }
        // 根据流程ID获取常规操作信息
        NormalOperationVo normalOperationVo = normalOperationMapper.findNormalOperationByPiid(piid);
        return normalOperationVo;
    }

    /**
     * 修改状态
     *
     * @param normalOperationVo
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int updateById(NormalOperationVo normalOperationVo, TaskLink taskLink) {
        int a = 0;
        // 根据常规操作ID获取常规操作信息
        NormalOperation normalOperation = normalOperationMapper.selectByPrimaryKey(normalOperationVo.getNormalOperationId());
        // 设置节点
        normalOperation.setNode((short) (normalOperationVo.getNode() + 1));
        // 现场操作中修改任务状态
        if (ConstantUtil.SPOT_OPERATION.equals(taskLink.getTaskLinkName())) {
            normalOperation.setTaskStatus((short) 2);
            // 流程处理完成修改任务状态
        } else if (ConstantUtil.CONFIRM.equals(taskLink.getTaskLinkName())) {
            normalOperation.setTaskStatus((short) 3);
            normalOperation.setFinishTime(new Date());
        }
        a += normalOperationMapper.updateByPrimaryKeySelective(normalOperation);
        return a;
    }

    /**
     * 处理流程
     *
     * @param employeeVo
     * @param normalOperationVo
     * @param workOrderList
     * @param taskLink
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int disposeTask(RedisValue redisValue, EmployeeVo employeeVo, NormalOperation normalOperationVo, List<WorkOrderVo> workOrderList, TaskLink taskLink) {
        // 标志变量
        int a = 0;
        // 流程参数
        String type = null;
        try {
            if (normalOperationVo.getAuditStatus() != null) {
                // 流程走向参数
                taskLink.setAuditStatus(normalOperationVo.getAuditStatus());
                String val = "{\"type\":\"" + normalOperationVo.getAuditStatus() + "\"}";
                type = URLEncoder.encode(val, "utf-8");
                logger.info("type" + type);
            } else {
                // 设置审核状态
                taskLink.setAuditStatus((short) 1);
            }
        } catch (UnsupportedEncodingException e) {
            logger.error(e.getMessage(), e);
        }
        //用户名
        String username = redisValue.getLoginName();
        //密码
        String password = redisValue.getPassWord();
        // 完成当前节点，往下一节点扭转
        String result = ibmbpmService.completeTask(username, password, taskLink.getTkiid(), type);

        //处理返回值为空串：执行了但是没有返回值
        if ("".equals(result)) {
            logger.info("完成“" + taskLink.getTaskLinkName() + "”返回值为空串！");
        } else {
            //获得返回值
            JSONObject resultObj = JSONObject.parseObject(result);
            if (resultObj != null) {
                String status = (String) resultObj.get("status");
                // 开始流程成功
                if (status != null && status.equals("200")) {
                    // 添加任务环节
                    taskLink.setTaskLinkId(UniqueUtil.uuid());
                    // 任务发起表存的是当前节点
                    taskLink.setNode(normalOperationVo.getNode());
                    // 设置任务类型
                    taskLink.setTaskType(normalOperationVo.getTaskType());
                    // 设置任务ID
                    taskLink.setTaskId(normalOperationVo.getNormalOperationId());
                    // 设置人员ID
                    taskLink.setUserId(employeeVo.getEmployeeId());
                    // 执行人组织
                    taskLink.setOrgId(employeeVo.getOrgId());
                    // 保存任务环节信息
                    a += taskLinkMapper.insertNew(taskLink);
                    // 删除任务下面的消息告知
                    a += messageImpartMapper.updateMessageStatusById(normalOperationVo.getNormalOperationId());
                    // 更新审核状态
                    normalOperationVo.setAuditStatus(taskLink.getAuditStatus());
                    a += normalOperationMapper.updateByPrimaryKeySelective(normalOperationVo);

                    //保存工单：删除旧工单，新增新工单 苏公车添加
                    a += workOrderService.saveWorkOrderList(employeeVo, taskLink, workOrderList);
                    //重新修改工单
                    if (("接受与指派(调度室)".equals(taskLink.getTaskLinkName()) || "接受与指派(专业技术岗)".equals(taskLink.getTaskLinkName())) && normalOperationVo.getAuditStatus() == 1) {
                        //进入现场操作：所有工单状态改为可用 苏公车添加
                        a += tdmWorkOrderMapper.updateStatusEnableByTaskId(normalOperationVo.getNormalOperationId());
                        normalOperationVo.setTaskStatus((short) 2);
                        a += normalOperationMapper.updateByPrimaryKeySelective(normalOperationVo);
                    }
                } else {
                    logger.error("完成“" + taskLink.getTaskLinkName() + "”返回状态非200！");
                }
            } else {
                logger.error("完成“" + taskLink.getTaskLinkName() + "”返回值非json字符串！");
            }
        }
        return a;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int launchBPM(RedisValue redisValue, EmployeeVo employeeVo, NormalOperation normalOperation, List<WorkOrderVo> workOrderList) throws Exception {
        int a = 0;

        //用户名
        String username = redisValue.getLoginName();
        //密码
        String password = redisValue.getPassWord();
        // 开启流程（调用BPM开启流程接口）
        String result = ibmbpmService.openBPM(employeeVo, (short) 2, username, password, null);

        // 流程实例ID
        String piid = null;
        // 任务节点ID
        String tkiid = null;
        // 任务节点名
        String name = null;
        JSONObject resultObj = JSONObject.parseObject(result);
        // 获取data属性的值
        JSONObject dataObj = (JSONObject) resultObj.get("data");
        // 获取tasks属性的值
        JSONArray itemsArray = (JSONArray) dataObj.get("tasks");
        // 循环json数组
        for (int i = 0; i < itemsArray.size(); i++) {
            // 得到json对象
            JSONObject ob = (JSONObject) itemsArray.get(i);
            // piid这里是列名称，获取json对象中列名为piid的值
            piid = ob.getString("piid");
            // tkiid这里是列名称，获取json对象中列名为tkiid的值
            tkiid = ob.getString("tkiid");
            // name这里是列名称，获取json对象中列名为name的值
            name = ob.getString("name");
        }

        // 判断生产计划、指令下达、岗位工作质量标准的参数：0：生产计划或者岗位工作质量标准，1：生产指令，2分析处理
        String val = "{'type':" + 2 + "}";
        // 转换编码
        String type = URLEncoder.encode(val, "utf-8");
        // 完成当前节点，往下一节点扭转
        result = ibmbpmService.completeTask(username, password, tkiid, type);

        //获得返回值
        resultObj = JSONObject.parseObject(result);
        if (resultObj != null && !"".equals(resultObj)) {
            String status = (String) resultObj.get("status");
            //完成任务成功
            if (status != null && status.equals("200")) {
                // 设置修改人ID
                normalOperation.setModifyUserId(employeeVo.getEmployeeId());
                // 设置发起时间
                normalOperation.setCreateTime(new Date());
                // 设置修改时间
                normalOperation.setModifyTime(new Date());
                normalOperation.setFlowId(piid);
                // 修改常规操作信息
                a += normalOperationMapper.updateByPrimaryKey(normalOperation);

                // 创建任务环节
                TaskLink taskLink = new TaskLink();
                // 设置流程实例ID
                taskLink.setPiPiid(piid);
                // 设置任务节点ID
                taskLink.setTkiid(tkiid);
                // 设置任务类型
                taskLink.setTaskType(normalOperation.getTaskType());
                // 设置任务ID
                taskLink.setTaskId(normalOperation.getNormalOperationId());
                // 设置环节名称
                taskLink.setTaskLinkName(name);
                // 设置任务节点
                taskLink.setNode(normalOperation.getNode());
                // 设置审核状态
                taskLink.setAuditStatus((short) 1);
                // 设置ID
                taskLink.setTaskLinkId(UniqueUtil.uuid());
                // 设置人员ID
                taskLink.setUserId(employeeVo.getEmployeeId());
                // 执行人组织
                taskLink.setOrgId(employeeVo.getOrgId());
                // 保存任务环节
                taskLinkMapper.insertNew(taskLink);

                //保存工单：删除旧工单，新增新工单
                a += workOrderService.saveWorkOrderList(employeeVo, taskLink, workOrderList);

                //进入现场操作：所有工单状态改为可用 苏公车添加
                a += tdmWorkOrderMapper.updateStatusEnableByTaskId(normalOperation.getNormalOperationId());
                normalOperation.setTaskStatus((short) 2);
                a += normalOperationMapper.updateByPrimaryKeySelective(normalOperation);
            } else {
                logger.error("完成常规操作流程第一个任务节点失败！");
            }
        } else {
            logger.error("完成常规操作流程第一个任务节点无返回值！");
        }
        return a;
    }

    /**
     * 根据任务实例ID查询任务表和任务环节表
     *
     * @param piPiid
     * @return
     */
    @Override
    public NormalOperationVo findVoByPiPiid(String piPiid) {
        if (StringUtils.isBlank(piPiid)) {
            return null;
        }
        NormalOperationVo normalOperationVo = normalOperationMapper.findVoByPiPiid(piPiid);
        return normalOperationVo;
    }

    /**
     * 根据主键查询
     *
     * @param id
     * @return
     */
    @Override
    public NormalOperationVo queryByPrimaryKey(String id) {
        NormalOperationVo normalOperation = normalOperationMapper.selectByPrimaryKey(id);
        return normalOperation;
    }

}
